<?php
class Smithy_Data_Table implements Iterator
{
    /**
     * The table's cols.
     *
     * @var array
     */
    protected $_cols = array();

    /**
     * The data recordset to be displayed.
     *
     * @var Iterator
     */
    protected $_data = null;

    /**
     * The table tag's attributes.
     *
     * @var array
     */
    protected $_attributes = array(
        'class'         => 'smithy-data-table',
        'cellspacing'   => '0px',
        'cellpadding'   => '0px'
    );

    /**
     * The table header's attributes.
     *
     * @var array
     */
    protected $_headerRowAttributes = array(
        'class' => 'smithy-data-table-headerRow'
    );

    /**
     * The table rows' attributes.
     *
     * @var array
     */
    protected $_rowAttributes = array(
        'class' => 'smithy-data-table-row-{num}'
    );


    /**
     * Constructor
     *
     * @param Iterator $data The data recordset to be displayed.
     * @return void
     */
    function __construct ($data = null)
    {
        if (!($data instanceof Iterator) && !($data instanceof IteratorAggregate)) {
            throw new Smithy_Data_Table_Exception('Parameter $data must implement Iterator or IteratorAggregate interface. ');
        }

        $this->_data = $data;
        $this->init();
    }

    /**
     * Initialize table.
     *
     * @return void
     */
    public function init()
    {}

    /**
     * Adds a new col to the table.
     *
     * @param array|Smithy_Data_Table_Col $data
     * @return Smithy_Data_Table
     */
    public function addCol($data, $headerAttribs = array(), $attribs = array())
    {
        if ($data instanceof Smithy_Data_Table_Col) {
            $this->_cols[] = $data;
        } elseif (is_array($data)) {
            $this->_cols[] = new Smithy_Data_Table_Col($data, $headerAttribs, $attribs);
        } else {
            throw new Exception('Data must be a col instance or array.');
        }

        return $this;
    }

    /**
     * Sets the table's cols.
     *
     * @param array|Iterator $data
     * @return Smithy_Data_Table
     */
    public function setCols($data)
    {
        foreach ($data as $col) {
            $this->addCol($col);
        }

        return $this;
    }

    /**
     * Adds a new or sets an existing attribute for the table.
     *
     * @param string $name
     * @param string $value
     * @return Smithy_Data_Table
     */
    public function addAttribute($name, $value)
    {
        $this->_attributes[$name] = $value;
        return $this;
    }

    /**
     * Sets the attributes for the table.
     *
     * @param array $attribs
     * @return Smithy_Data_Table
     */
    public function setAttributes($attribs)
    {
        foreach ($attribs as $name => $value) {
            $this->addAttribute($name, $value);
        }
        return $this;
    }

    /**
     * Sets the table's data to be displayed.
     *
     * @param Iterator $data
     * @return Smithy_Data_Table
     */
    public function setData(Iterator $data)
    {
        $this->_data = $data;
        return $this;
    }

    /**
     * Renders the table.
     *
     * @return string The html source of the table.
     */
    public function render()
    {
        $source = '<table '.$this->_renderAttributes($this->_attributes).'><tr '.$this->_renderAttributes($this->_headerRowAttributes).'>' . "\n";
        foreach ($this->_cols as $headerCol) {
            $source .= '    ' . $headerCol->renderHeader();
        }
        $source .= '</tr>' . "\n";
        $i = 0;
        foreach ($this->_data as $row) {
            $i = 0 === $i ? 1 : 0;
            $class = $this->_rowAttributes['class'];
            $this->_rowAttributes['class'] = str_replace('{num}', $i, $this->_rowAttributes['class']);
            $source .= '<tr '.$this->_renderAttributes($this->_rowAttributes).'>' . "\n";
            $this->_rowAttributes['class'] = $class;

            foreach ($this->_cols as $col) {
                $source .= $col->render($row);
            }
            $source .= "</tr>\n";
        }
        $source .= '</table>';

        return $source;
    }

    /**
     * Renders the table's attributes.
     *
     * @param array $attribs
     * @return unknown
     */
    protected function _renderAttributes($attribs)
    {
        $src = '';
        foreach ($attribs as $name => $value) {
            $src .= $name . '="' . $value . '" ';
        }
        return $src;
    }

    /**
     *
     * @see Iterator::current()
     */
    public function current ()
    {
        return $this->_data->current();
    }

    /**
     *
     * @see Iterator::key()
     */
    public function key ()
    {
        return $this->_data->key();
    }

    /**
     *
     * @see Iterator::next()
     */
    public function next ()
    {
        return $this->_data->next();
    }

    /**
     *
     * @see Iterator::rewind()
     */
    public function rewind ()
    {
        return $this->_data->rewind();
    }

    /**
     *
     * @see Iterator::valid()
     */
    public function valid ()
    {
        return $this->_data->valid();
    }

}
